# coding=utf-8
from django.db import transaction
from rest_framework import serializers
from rest_framework.exceptions import ValidationError

from purchase_info.models import PurchaseModel,PurchaseItemModel
from MSB_ERP.utils.get_inventory import get_inventory


class PurchaseItemSerializer(serializers.ModelSerializer):
    '''
    采购项目和序列化器
    '''
    class Meta:
        model = PurchaseItemModel
        fields = '__all__'

class PurchaseSerializer(serializers.ModelSerializer):
    '''
    新增和修改采购订单的序列化和反序列化
    '''
    item_list = PurchaseItemSerializer(many=True,write_only=True)
    # 采购订单列表中需要展示：商品信息.多个商品的名字+规格，中间使用逗号隔开组成的
    # serializers.SerializerMethodField表示通过函数进行处理
    goods_info = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = PurchaseModel
        fields = '__all__'

    def get_goods_info(self,obj):
        '''
        商品信息是由：商品1名称 商品1规格，商品2名称 商品2规格，...
        '''
        if obj.item_list.all(): # item_list属性通过.all可以把整个项目的所有列表全部拿出来，.all返回的是列表
            result = []
            for item in obj.item_list.all():
                # item.name返回的是商品名称
                # item.specification if item.specification else ''是三位换算符
                # ==> if item.specification 如果有这个属性的值的话就用这个属性的值item.specification
                # 判断成功的话结果放if前面，else的话就用空字符
                result.append(item.name + (item.specification if item.specification else ''))
            # 返回的是一个列表，列表的每一个值都是用逗号去隔开
            return ','.join(result) # 把列表全部展开，每一值之间都用，隔开
        return '' # 其他情况下就返回一个空的字符串

    # 添加采购订单的业务
    def create(self, validated_data):
        item_list = validated_data.pop('item_list')
        with transaction.atomic(): # 数据库事务（最灵活的），要不一起成功要不一起失败
            purchase = PurchaseModel.objects.create(**validated_data)
            for item in item_list:
                pim = PurchaseItemModel.objects.create(purchase=purchase,**item)
                goods = item.get('goods')
                pim.name = goods.name
                pim.specification = goods.specification
                pim.number_code = goods.number_code

                pim.save()
        return purchase

    def update(self, instance, validated_data):
        # instance表示正在修改的采购订单
        if instance.status != '0':
            # 只要抛了异常后面的就不会执行了
            raise ValidationError('采购订单已经生效，不能修改')

        item_list = validated_data.pop('item_list')

        # 把之前的老数据（之前新增的采购订单项目数据）删除
        # 这个拿的是反向关联属性的名字，也就是PurchaseItemModel里面的purchas内容
        old_list = instance.item_list.all() # 这是一个query对象，只有.all ...才是真正的列表
        with transaction.atomic(): # 数据库事务（最灵活的），要不一起成功要不一起失败
            if old_list.exists(): # 列表中自带的属性，叫列表中是否有数据
                # 意味着有老数据，要删除
                instance.item_list.all().delete() # 他会删除列表也会自动删除数据库里面的数据，他是跟数据库进行映射的

            for item in item_list:
                pim = PurchaseItemModel.objects.create(purchase=instance, **item)
                goods = item.get('goods')
                pim.name = goods.name
                pim.specification = goods.specification
                pim.number_code = goods.number_code

                pim.save()
            result=super(PurchaseSerializer, self).update(instance=instance, validated_data=validated_data)
        return result

class PurchaseGetSerializer(serializers.ModelSerializer):
    '''
    仅仅用于查询单个采购订单的序列化器
    '''
    item_list = serializers.SerializerMethodField(read_only=True)

    class Meta:
        model = PurchaseModel
        fields = '__all__'

    # 序列化的作用就是把对象变成字典或者列表
    def get_item_list(self,obj):
        result = [] # 返回的列表，列表中是多个字典
        # obj.item_list这里是通过PurchaseItemModel的purchase字段的反向关联名字item_list定义到PurchaseModel表中的
        if obj.item_list.all().exists(): # exists如果存在有值的话
            for item in obj.item_list.all(): # item是一个PurchaseItrmModel对象
                # 有一部分信息在PurchaseItrmModel里面没有
                # 只有在GoodsModel里面有：颜色，型号，单位
                item_dict = {}
                goods = item.goods
                item_dict['goods'] = goods.id
                item_dict['name'] = goods.name
                item_dict['number_code'] = goods.number_code
                item_dict['specification'] = goods.specification
                item_dict['model_number'] = goods.model_number
                item_dict['color'] = goods.color
                item_dict['units'] = goods.units.basic_name
                item_dict['remark'] = item.remark

                # 该商品的总库存数量
                item_dict['cur_inventory'] = get_inventory(goods.id)
                result.append(item_dict)

            return result



